//size属性返回 Map 结构的成员总数。
const map = new Map();
map.set('foo', true);
map.set('bar', false);
map.size // 2




//set方法设置键名key对应的键值为value， 如果key已经有值， 则键值会被更新， 否则就新生成该键。
const m = new Map();
m.set('edition', 6) // 键是字符串
m.set(262, 'standard') // 键是数值
m.set(undefined, 'nah') // 键是 undefined  注意:set会返回整个 Map 结构。
let map = new Map() //注意:set会返回整个 Map 结构。因此可以采用链式写法。
	.set(1, 'a')
	.set(2, 'b')
	.set(3, 'c');



//get方法读取key对应的键值， 如果找不到key， 返回undefined。
const m = new Map();
const hello = function() {
	console.log('hello');
};
m.set(hello, 'Hello ES6!') // 键是函数
m.get(hello) // Hello ES6!



//has方法返回一个布尔值，表示某个键是否在当前 Map 对象之中。
const m = new Map();
m.set('edition', 6);
m.set(262, 'standard');
m.set(undefined, 'nah');
m.has('edition') // true
m.has('years') // false
m.has(262) // true
m.has(undefined) // true



//delete方法删除某个键，返回true。如果删除失败，返回false。
const m = new Map();
m.set(undefined, 'nah');
m.has(undefined) // true
m.delete(undefined)
m.has(undefined) // false




//clear方法清除所有成员， 没有返回值。
let map = new Map();
map.set('foo', true);
map.set('bar', false);
map.size // 2
map.clear()
map.size // 0





/*
Map 结构原生提供三个遍历器生成函数和一个遍历方法。

    Map.prototype.keys()：返回键名的遍历器。
    Map.prototype.values()：返回键值的遍历器。
    Map.prototype.entries()：返回所有成员的遍历器。
    Map.prototype.forEach()：遍历 Map 的所有成员。

*/


//需要特别注意的是， Map 的遍历顺序就是插入顺序。
const map = new Map([
	['F', 'no'],
	['T', 'yes'],
]);

for (let key of map.keys()) {
	console.log(key);
}
// "F"
// "T"

for (let value of map.values()) {
	console.log(value);
}
// "no"
// "yes"

for (let item of map.entries()) {
	console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"

// 或者
for (let [key, value] of map.entries()) {
	console.log(key, value);
}
// "F" "no"
// "T" "yes"

// 等同于使用map.entries()   map可直接遍历 和set一样
for (let [key, value] of map) {
	console.log(key, value);
}
// "F" "no"
// "T" "yes"



//Map 结构转为数组结构，比较快速的方法是使用扩展运算符（...）。
const map = new Map([
	[1, 'one'],
	[2, 'two'],
	[3, 'three'],
]);
[...map.keys()]
// [1, 2, 3]
[...map.values()]
// ['one', 'two', 'three']
[...map.entries()]
// [[1,'one'], [2, 'two'], [3, 'three']]
[...map]
// [[1,'one'], [2, 'two'], [3, 'three']]





//结合数组的map方法、 filter方法， 可以实现 Map 的遍历和过滤（ Map 本身没有map和filter方法）。
const map0 = new Map()
	.set(1, 'a')
	.set(2, 'b')
	.set(3, 'c');

const map1 = new Map(
	[...map0].filter(([k, v]) => k < 3)
);
// 产生 Map 结构 {1 => 'a', 2 => 'b'}

const map2 = new Map(
	[...map0].map(([k, v]) => [k * 2, '_' + v])
);
// 产生 Map 结构 {2 => '_a', 4 => '_b', 6 => '_c'}



/*

map与其他数据类型的转换

*/

//前面已经提过， Map 转为数组最方便的方法， 就是使用扩展运算符（...）。
const myMap = new Map()
	.set(true, 7)
	.set({
		foo: 3
	}, ['abc']);
[...myMap]
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]



//将数组传入 Map 构造函数，就可以转为 Map。
new Map([
	[true, 7],
	[{
			foo: 3
		},
		['abc']
	]
])
// Map {
//   true => 7,
//   Object {foo: 3} => ['abc']
// }




//如果所有 Map 的键都是字符串，它可以无损地转为对象。
function strMapToObj(strMap) {
	let obj = Object.create(null);
	for (let [k, v] of strMap) {
		obj[k] = v;
	}
	return obj;
}
const myMap = new Map()
	.set('yes', true)
	.set('no', false);
strMapToObj(myMap)
// { yes: true, no: false }  如果有非字符串的键名， 那么这个键名会被转成字符串， 再作为对象的键名。




//对象转为 Map 可以通过Object.entries()。
let obj = {
	"a": 1,
	"b": 2
};
let map = new Map(Object.entries(obj));





//Map 转为 JSON 要区分两种情况。一种情况是，Map 的键名都是字符串，这时可以选择转为对象 JSON。
function strMapToJson(strMap) {
	return JSON.stringify(strMapToObj(strMap));
}
let myMap = new Map().set('yes', true).set('no', false);
strMapToJson(myMap)
// '{"yes":true,"no":false}'
